package com.gitee.wsl.struct.combine

import com.gitee.wsl.struct.combine.BModifier.Element

interface BModifier<E:Element<E>> {

    /**
     * Accumulates a value starting with [initial] and applying [operation] to the current value
     * and each element from outside in.
     *
     * Elements wrap one another in a chain from left to right; an [Element] that appears to the
     * left of another in a `+` expression or in [operation]'s parameter order affects all
     * of the elements that appear after it. [foldIn] may be used to accumulate a value starting
     * from the parent or head of the modifier chain to the final wrapped child.
     */
    fun <R> foldIn(initial: R, operation: (R, E) -> R): R

    /**
     * Accumulates a value starting with [initial] and applying [operation] to the current value
     * and each element from inside out.
     *
     * Elements wrap one another in a chain from left to right; an [Element] that appears to the
     * left of another in a `+` expression or in [operation]'s parameter order affects all
     * of the elements that appear after it. [foldOut] may be used to accumulate a value starting
     * from the child or tail of the modifier chain up to the parent or head of the chain.
     */
    fun <R> foldOut(initial: R, operation: (E, R) -> R): R

    /**
     * Returns `true` if [predicate] returns true for any [Element] in this [BModifier].
     */
    fun any(predicate: (E) -> Boolean): Boolean

    /**
     * Returns `true` if [predicate] returns true for all [Element]s in this [BModifier] or if
     * this [BModifier] contains no [Element]s.
     */
    fun all(predicate: (E) -> Boolean): Boolean

    /**
     * Concatenates this modifier with another.
     *
     * Returns a [BModifier] representing this modifier followed by [other] in sequence.
     */
    infix fun then(other: E): E
    //=if (other === BModifier) this else BCombinedTModifier(this, other)

    /**
     * A single element contained within a [BModifier] chain.
     */
   
    interface Element<E:Element<E>> : BModifier<E> {
        fun self():E
        override fun <R> foldIn(initial: R, operation: (R, E) -> R): R = operation(initial, self())
        override fun <R> foldOut(initial: R, operation: (E, R) -> R): R = operation(self(), initial)
        override fun any(predicate: (E) -> Boolean): Boolean = predicate(self())
        override fun all(predicate: (E) -> Boolean): Boolean = predicate(self())
    }

    /**
     * The companion object `Modifier` is the empty, default, or starter [BModifier]
     * that contains no [elements][Element]. Use it to create a new [BModifier] using
     * modifier extension factory functions:
     *
     * @sample androidx.compose.ui.samples.ModifierUsageSample
     *
     * or as the default value for [BModifier] parameters:
     *
     * @sample androidx.compose.ui.samples.ModifierParameterSample
     */
    // The companion object implements `Modifier` so that it may be used as the start of a
    // modifier extension factory expression.
//    companion object : BModifier {
//        override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R = initial
//        override fun <R> foldOut(initial: R, operation: (Element, R) -> R): R = initial
//        override fun any(predicate: (Element) -> Boolean): Boolean = false
//        override fun all(predicate: (Element) -> Boolean): Boolean = true
//        override infix fun then(other: BModifier): BModifier = other
//        override fun toString() = "Modifier"
//    }


}

